package org.Yiran.timetale_re;

import net.minecraft.data.loot.LootTableProvider;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraftforge.client.event.ModelEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.Yiran.timetale_re.block.BlocksRegister;
import org.Yiran.timetale_re.block.decorate.longtable.LongTableCarvingHandler;
import org.Yiran.timetale_re.capability.RuneCraftingProficiency;
import org.Yiran.timetale_re.compileOnlyMod.TConstructCompat;
import org.Yiran.timetale_re.createtab.CreativeTabRegister;
import org.Yiran.timetale_re.datagen.*;
import org.Yiran.timetale_re.entity.EntityRegister;
import org.Yiran.timetale_re.item.ItemsRegister;
import org.Yiran.timetale_re.item.MaterialRegister;
import org.Yiran.timetale_re.item.material.ModMaterials;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.Modules;
import org.Yiran.timetale_re.menu.MenuRegister;
import org.Yiran.timetale_re.network.NetworkChannel;
import org.Yiran.timetale_re.recipe.ModRecipes;
import org.Yiran.timetale_re.sound.ModSounds;
import org.Yiran.timetale_re.tile.TileEntityRegister;
import org.Yiran.timetale_re.worldgen.ModWorldGen;

import java.util.List;
import java.util.Set;

/**
 * TimeTale模组主类
 * <p>
 * 负责模组的初始化工作，包括注册各种游戏对象（方块、物品、实体等）、
 * 设置事件监听器、初始化网络通信和数据生成器等核心功能。
 * </p>
 *
 * @author Yiran
 * @version 1.0
 */
@Mod(Timetale_re.MODID)
public class Timetale_re {
    
    // ================================
    // 常量定义
    // ================================
    
    /**
     * 模组ID
     */
    public static final String MODID = "timetale_re";

    // ================================
    // 构造方法和初始化
    // ================================
    
    /**
     * 模组构造函数
     * <p>
     * 在模组加载时执行初始化操作，包括注册各种游戏对象和事件监听器
     * </p>
     *
     * @param context FML Java模组加载上下文
     */
    public Timetale_re(FMLJavaModLoadingContext context) {
        IEventBus modEventBus = context.getModEventBus();
        
        // 初始化材料系统
        ModMaterials.init();
        // 注册实体
        EntityRegister.ENTITIES.register(modEventBus);

        // 注册方块
        BlocksRegister.BLOCKS.register(modEventBus);
        MaterialRegister.MATERIAL_BLOCKS.register(modEventBus);

        // 注册物品
        ItemsRegister.ITEMS.register(modEventBus);
        MaterialRegister.MATERIAL_ITEMS.register(modEventBus);

        // 注册方块实体
        TileEntityRegister.TILE_ENTITIES.register(modEventBus);

        // 注册创造模式物品栏
        CreativeTabRegister.CREATIVE_TABS.register(modEventBus);

        // 注册音效
        ModSounds.register(modEventBus);

        // 注册菜单
        MenuRegister.MENUS.register(modEventBus);
        
        // 注册世界生成相关内容
        ModWorldGen.register(modEventBus);
        
        // 注册配方
        ModRecipes.RECIPE_SERIALIZERS.register(modEventBus);
        ModRecipes.RECIPE_TYPES.register(modEventBus);

        modEventBus.addListener(this::registerCapabilities);
        modEventBus.addListener(this::commonSetup);
        modEventBus.addListener(this::clientSetup);
        modEventBus.addListener(this::gatherData);
        modEventBus.addListener(this::registerModels);
        
        // 注册事件总线
        MinecraftForge.EVENT_BUS.register(this);
    }

    // ================================
    // 能力注册方法
    // ================================
    
    /**
     * 注册模组能力
     * <p>
     * 注册符文制作熟练度能力系统
     * </p>
     *
     * @param event 能力注册事件
     */
    private void registerCapabilities(RegisterCapabilitiesEvent event) {
        event.register(RuneCraftingProficiency.class);
    }

    // ================================
    // 数据生成方法
    // ================================
    
    /**
     * 收集数据生成器
     * <p>
     * 注册模组的数据生成器，包括配方、方块标签和物品标签生成器
     * </p>
     *
     * @param event 数据收集事件
     */
    private void gatherData(final net.minecraftforge.data.event.GatherDataEvent event) {
        var generator = event.getGenerator();
        var packOutput = generator.getPackOutput();

        System.out.println("数据生成事件触发，包含服务器：" + event.includeServer());
        System.out.println("开始注册数据提供者...");

        if (event.includeServer()) {
            System.out.println("服务器数据生成已启用，正在添加数据提供者...");
            
            // 添加配方提供者
            System.out.println("添加配方提供者...");
            generator.addProvider(true, new ModRecipeProvider(packOutput));
            generator.addProvider(true, new ModAnvilForgeRecipeProvider(packOutput));
            System.out.println("配方提供者已添加");
            
            // 添加方块标签生成器
            System.out.println("添加方块标签生成器...");
            generator.addProvider(event.includeServer(),
                    new BlockTagsGenerator(packOutput, event.getLookupProvider(), event.getExistingFileHelper()));
            System.out.println("方块标签生成器已添加");

            // 添加物品标签生成器
            System.out.println("添加物品标签生成器...");
            generator.addProvider(event.includeServer(),
                    new ModItemTagsProvider(packOutput, event.getLookupProvider(), event.getExistingFileHelper()));
            System.out.println("物品标签生成器已添加");
            
            // 添加世界生成数据提供者
            System.out.println("添加世界生成数据提供者...");
            generator.addProvider(event.includeServer(), new ModWorldGenProvider(packOutput, event.getLookupProvider()));
            System.out.println("世界生成数据提供者已添加");

            // 添加方块战利品表生成器
            System.out.println("添加方块战利品表生成器...");
            generator.addProvider(event.includeServer(), new LootTableProvider(packOutput, Set.of(), List.of(
                    new LootTableProvider.SubProviderEntry(ModBlockLootTables::new, LootContextParamSets.BLOCK)
            )));
            System.out.println("方块战利品表生成器已添加");
            
            System.out.println("所有数据提供者注册完成");
        } else {
            System.out.println("服务器数据生成未启用，跳过数据提供者添加");
        }
        
        System.out.println("数据生成器注册流程结束");
    }

    // ================================
    // 通用设置方法
    // ================================
    
    /**
     * 通用设置
     * <p>
     * 执行模组的通用初始化操作，包括网络消息注册和模组兼容性初始化
     * </p>
     *
     * @param event 通用设置事件
     */
    private void commonSetup(final FMLCommonSetupEvent event) {
        NetworkChannel.registerMessage();

        // 初始化模组兼容性功能
        TConstructCompat.init();
        
        // 初始化模块系统
        Modules.init();
        
        // 注册材料的世界生成特征
        event.enqueueWork(MaterialRegister::registerWorldGenFeatures);
    }

    // ================================
    // 客户端设置方法
    // ================================
    
    /**
     * 客户端设置
     * <p>
     * 执行客户端专用的初始化操作
     * </p>
     *
     * @param event 客户端设置事件
     */
    private void clientSetup(final FMLClientSetupEvent event) {
        // 不再需要注册物品属性，因为我们现在使用独立的起子类和模型
    }

    // ================================
    // 模型注册方法
    // ================================
    
    /**
     * 注册额外模型
     * <p>
     * 注册符文蓝图等相关模型资源
     * </p>
     *
     * @param event 模型注册事件
     */
    private void registerModels(ModelEvent.RegisterAdditional event) {
        // 注册所有符文蓝图模型
        String[] runeTypes = {
                "life",
                "storm" ,
                "thunder",

        };
        for (String type : runeTypes) {
            // 修改为正确的模型路径注册方式
            ResourceLocation modelLocation = ResourceLocation.fromNamespaceAndPath(
                    "timetale_re",
                    "block/rune_blueprint/rune_blueprint_" + type
            );
            event.register(modelLocation);
        }
    }

    // ================================
    // 服务器事件处理方法
    // ================================
    
    /**
     * 服务器启动事件处理
     * <p>
     * 在服务器启动时执行相关操作
     * </p>
     *
     * @param event 服务器启动事件
     */
    @SubscribeEvent
    public void onServerStarting(ServerStartingEvent event) {
    }

    /**
     * 世界Tick事件处理
     * <p>
     * 在世界每个tick结束时清理长桌雕刻冷却数据
     * </p>
     *
     * @param event 世界tick事件
     */
    @SubscribeEvent
    public static void onWorldTick(TickEvent.LevelTickEvent event) {
        if (event.phase == TickEvent.Phase.END && !event.level.isClientSide) {
            LongTableCarvingHandler.cleanUpCarvingCooldowns(event.level);
        }
    }
}